package com.chaoyue.base.utils;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;

import com.beust.jcommander.internal.Lists;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import javax.xml.datatype.XMLGregorianCalendar;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Hutool 的日期增强 优先使用 该工具类
 * 还使用Date 需要考虑兼容老版本
 * * @Author caolj2
 *
 * @since 2019/9/22
 */
@Slf4j
@UtilityClass
public class DateUtils extends DateUtil {

    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss");
    public static final DateTimeFormatter TIME_FORMDAY = DateTimeFormatter.ofPattern("HH:mm:ss");
    public static final DateTimeFormatter TIME_FORMATTER_HH_MM = DateTimeFormatter.ofPattern("HH:mm");
    public static final DateTimeFormatter YEAR_MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM");
    public static final DateTimeFormatter SHORT_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter SHORT_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter LONG_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS");
    public static final DateTimeFormatter DATE_FORMATTER_POINT = DateTimeFormatter.ofPattern("yyyy.MM.dd");

    public static final long SECOND = 1000;
    public static final long MINUTE = SECOND * 60;
    public static final long HOUR = MINUTE * 60;
    public static final long DAY = HOUR * 24;
    public static final long WEEK = DAY * 7;
    public static final long YEAR = DAY * 365; // or 366 ???

    private static final int INTERVALS_PER_DAY = 1440; // 24 hours * 60 minutes/hour

    public static final String ADD_TYPE_YYYY = "YYYY";
    public static final String ADD_TYPE_YY = "YY";
    public static final String ADD_TYPE_MM = "MM";
    public static final String ADD_TYPE_M = "M";
    public static final String ADD_TYPE_WW = "WW";
    public static final String ADD_TYPE_W = "W";
    public static final String ADD_TYPE_DD = "DD";
    public static final String ADD_TYPE_D = "D";


    /**
     * This is the time difference between GMT time and Vietnamese time
     */
    public static final long GMT_VIETNAM_TIME_OFFSET = HOUR * 7;
    public static final String DEFAULT_DATE = "1900-1-1";
    public static final String TIME_HH_MM_23_59 = "23:59";
    /**
     * RFC 822 date format
     */
    public static final String RFC_822_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss Z";
    /**
     * ISO 8601 [W3CDTF] date format
     */
    public static final String ISO_8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
    /**
     * UTC style date format
     */
    public static final String UTC_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    /**
     * 系统默认日期格式：2008-12-10 21:01
     */
    public static final String DEFAULT_DATE_ONLY_PATTERN = "yyyy-MM-dd";
    /**
     * 系统默认日期格式：2008-12-10 21:01
     */
    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm";
    public static final String DEFAULT_DATE_PATTERN2 = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATE_PATTERN3 = "yyyyMMddHHmmss";
    public static final String DEFAULT_DATE_PATTERN4 = "yyyyMMddHHmm";
    public static final String DEFAULT_DATE_PATTERN5 = "yyyyMMdd";
    public static final String DEFAULT_DATE_PATTERN6 = "HHmm";
    public static final String DEFAULT_DATE_PATTERN7 = "HH:mm";
    public static final String DEFAULT_DATE_PATTERN8 = "dd-MMM-yy";
    public static final String DEFAULT_DATE_PATTERN9 = "dd-M月-yy";
    public static final String DEFAULT_DATE_PATTERN10 = "MM/dd/yyyy HH:mm:ss";
    public static final String DEFAULT_DATE_PATTERN11 = "MM/dd/yyyy";
    public static final String DEFAULT_DATE_PATTERN12 = "yyyy-MM";
    public static final String DEFAULT_DATE_PATTERN13 = "MM-dd";
    public static final String DEFAULT_DATE_PATTERN_YEAR = "yyyy";
    public static final String DEFAULT_DATE_PATTERN_MONTH = "yyyyMM";
    public static final String DEFAULT_DATE_PATTERN_POINT = "yyyy.MM.dd";

    /**
     * This is the time difference between GMT time and SERVER time
     */
    public static final String SCHEMA_DATE_JAVA = "yyyy-MM-dd";
    public static final String SCHEMA_DATE_JAVA1 = "yyyy/MM/dd";
    public static final String SCHEMA_TIME_JAVA = "HH:mm:ss";
    private static final String SCHEMA_DATE_JAVA_WITH_HM = "yyyy-MM-dd HH:mm";
    private static final String SCHEMA_DATE_JAVA_WITH_HMS = "yyyy-MM-dd HH:mm:ss";
    private static final String PATTERN_DATE = "\\d{4}-\\d{1,2}-\\d{1,2}";
    private static final String PATTERN_DATE1 = "\\d{4}/\\d{1,2}/\\d{1,2}";
    private static final String PATTERN_DATE_WITH_HM = "\\d{4}-\\d{1,2}-\\d{1,2}\\s{1}\\d{1,2}:\\d{1,2}";
    private static final String PATTERN_DATE_WITH_HMS = "\\d{4}-\\d{1,2}-\\d{1,2}\\s{1}\\d{1,2}:\\d{1,2}:\\d{1,2}";

    private static final String SCHEMA_DATE_JAVA_NOSEPARATOR = "yyyyMMdd";
    private static final String SCHEMA_DATE_JAVA_NOSEPARATOR_WITH_HM = "yyyyMMddHHmm";
    private static final String SCHEMA_DATE_JAVA_NOSEPARATOR_WITH_HMS = "yyyyMMddHHmmss";
    private static final String PATTERN_DATE_NOSEPARATOR = "\\d{8}";
    private static final String PATTERN_DATE_NOSEPARATOR_WITH_HM = "\\d{12}";
    private static final String PATTERN_DATE_NOSEPARATOR_WITH_HMS = "\\d{14}";
    /**
     * 取得格式化的两个时间差，结束时间应大于开始时间
     *
     * @param tStart 开始时间的getTime()值，long类型
     * @param tEnd   结束时间的getTime()值，long类型
     * @return 格式化的时间差值，如100 [y] 0 [m] 25 [d] 0 [h] 5 [min] 52 [s]
     */
    private static final String MIN_STR = " [min] ";
    private static final String H_STR = " [h] ";
    private static final String D_STR = " [d] ";
    /**
     * 默认的日期格式
     */
    private static String defaultDatePattern = DEFAULT_DATE_ONLY_PATTERN;
    /**
     * 默认的时间格式
     */
    private static String timePattern = "HH:mm:ss";

    private static final String MAX_END_DATE = "9999-12-31 23:59:59";
    private static final String MIN_END_DATE = "1970-01-01 23:59:59";

    static {
        TimeZone gmt = TimeZone.getTimeZone("GMT");
        DateFormat headerTimeFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
        headerTimeFormat.setTimeZone(gmt);
    }

    /**
     * 获取最大的日期
     */
    public static Date getMaxDate() {
        return DateUtils.formatDate(MAX_END_DATE, DateUtils.DEFAULT_DATE_PATTERN2);
    }

    /**
     * 获取最小的日期
     */
    public static Date getMinDate() {
        return DateUtils.formatDate(MIN_END_DATE, DateUtils.DEFAULT_DATE_PATTERN2);
    }

    /**
     * yyyy-MM-dd
     */
    public static String getCurrentDateStr() {
        return LocalDate.now().format(DATE_FORMATTER);
    }

    /**
     * yyMMdd
     */
    public static String getCurrentShortDateStr() {
        return LocalDate.now().format(SHORT_DATE_FORMATTER);
    }

    /**
     * yyyy-MM
     */
    public static String getCurrentMonthStr() {
        return LocalDate.now().format(YEAR_MONTH_FORMATTER);
    }

    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static String getCurrentDateTimeStr() {
        return LocalDateTime.now().format(DATETIME_FORMATTER);
    }

    /**
     * yyyy-MM-dd HH:mm:ss SSS
     */
    public static String getCurrentLongDateTimeStr() {
        return LocalDateTime.now().format(LONG_DATETIME_FORMATTER);
    }

    /**
     * yyMMddHHmmss
     */
    public static String getCurrentShortDateTimeStr() {
        return LocalDateTime.now().format(SHORT_DATETIME_FORMATTER);
    }

    /**
     * HHmmss
     */
    public static String getCurrentTimeStr() {
        return LocalTime.now().format(TIME_FORMATTER);
    }

    /**
     * yyyy-MM-dd
     *
     * @param date 时间 需要转换的日期
     * @return yyyy-MM-dd字符串
     */
    public static String formatLocalDate(LocalDate date) {
        return date.format(DATE_FORMATTER);
    }

    /**
     * yyyy-MM-dd HH:mm:ss
     *
     * @param datetime 需要转换的日期时间
     * @return yyyy-MM-dd HH:mm:ss字符串
     */
    public static String formatLocalDateTime(LocalDateTime datetime) {
        return datetime.format(DATETIME_FORMATTER);
    }

    /**
     * HHmmss
     *
     * @param time 时间
     * @return HHmmss 字符串
     */
    public static String formatLocalTime(LocalTime time) {
        return time.format(TIME_FORMATTER);
    }

    /**
     * 日期相隔秒
     */
    public static long periodSeconds(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        return Duration.between(startDateTime, endDateTime).get(ChronoUnit.SECONDS);
    }

    /**
     * 日期相隔小时
     */
    public static long periodHour(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        return Duration.between(startDateTime, endDateTime).get(ChronoUnit.HOURS);
    }

    /**
     * 日期相隔天数
     */
    public static long periodDays(LocalDate startDate, LocalDate endDate) {
        return startDate.until(endDate, ChronoUnit.DAYS);
    }

    /**
     * 日期相隔周数
     */
    public static long periodWeeks(LocalDate startDate, LocalDate endDate) {
        return startDate.until(endDate, ChronoUnit.WEEKS);
    }

    /**
     * 日期相隔月数
     */
    public static long periodMonths(LocalDate startDate, LocalDate endDate) {
        return startDate.until(endDate, ChronoUnit.MONTHS);
    }

    /**
     * 日期相隔年数
     */
    public static long periodYears(LocalDate startDate, LocalDate endDate) {
        return startDate.until(endDate, ChronoUnit.YEARS);
    }

    /**
     * 获取当前毫秒数
     */
    public static Long toEpochMilli(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 判断是否为闰年
     */
    public static boolean isLeapYear(LocalDate localDate) {
        return localDate.isLeapYear();
    }

    /**
     * 获取日期部分
     *
     * @param
     * @return
     */
    public static DateTime parseDate(Date date) {
        return parseDate(formatDate(date));
    }

    public static String getDateDDMMYYYY(Date date) {
        DateFormat ddMMyyyyFormat = new SimpleDateFormat("dd/MM/yyyy");
        return ddMMyyyyFormat.format(date);
    }

    public static String getDateYYYYMMDD(Date date) {
        DateFormat yyyyMMddFormat = new SimpleDateFormat(DEFAULT_DATE_ONLY_PATTERN);
        return yyyyMMddFormat.format(date);
    }

    public static String getDateYYYYMMddHHmmss(Date data) {
        DateFormat yyyyMMddHHmmssFormat = new SimpleDateFormat(SCHEMA_DATE_JAVA_WITH_HMS);
        return yyyyMMddHHmmssFormat.format(data);
    }

    public static String getDateHHmmss(Date data) {
        DateFormat HHmmssFormat = new SimpleDateFormat(SCHEMA_TIME_JAVA);
        return HHmmssFormat.format(data);
    }

    public static String getDateYYYYMMDD2(Date date) {
        DateFormat yyyyMMddFormat2 = new SimpleDateFormat("yyyy年MM月dd日");
        return yyyyMMddFormat2.format(date);
    }

    public static String getDateYYYYMM(Date date) {
        DateFormat yyyyMMFormat = new SimpleDateFormat("yyyy年MM月");
        return yyyyMMFormat.format(date);
    }

    public static String getDateYYYY(Date date) {
        DateFormat yyyyMMFormat = new SimpleDateFormat("yyyy");
        return yyyyMMFormat.format(date);
    }

    public static String yearAndHalf(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return StrUtil.builder().append(cal.get(1)).append(cal.get(2) / 6 + 1).toString();
    }

    public static String getDateRFC822(Date date) {
        DateFormat rfc822Format = new SimpleDateFormat(RFC_822_DATE_FORMAT, Locale.US);
        return rfc822Format.format(date);
    }

    public static String getDateISO8601(Date date) {
        DateFormat iso8601Format = new SimpleDateFormat(ISO_8601_DATE_FORMAT, Locale.US);
        return iso8601Format.format(date);
    }

    public static String getHTTPHeaderTime(Date date) {
        DateFormat headerTimeFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
        return headerTimeFormat.format(date);
    }

    public static String formatDate(Date date) {
        DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.DEFAULT);
        return dateFormat.format(date);
    }

    public static String formatDateTime(Date date) {
        DateFormat datetimeFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT);
        return datetimeFormat.format(date);
    }

    public static Date formatDate(String date, String pattern) {
        return formatDate(date, new SimpleDateFormat(pattern));
    }

    /**
     * 将日期字符串转换为Date类型的日期
     *
     * @param date 日期字符串(14位长度的日期字串)
     * @param sf   格式化器
     * @return 转换后的Date
     */
    public static Date formatDate(String date, SimpleDateFormat sf) {
        try {
            return sf.parse(date);
        } catch (ParseException pe) {
            log.error(pe.getMessage());
            return null;
        }
    }

    public static Timestamp getCurrentGMTTimestamp() {
        return new Timestamp(System.currentTimeMillis() - (HOUR * 0));
    }

    public static void updateCurrentGMTTimestamp(Timestamp timeToUpdate) {
        timeToUpdate.setTime(System.currentTimeMillis() - (HOUR * 0));
    }

    public static Date getVietnamDateFromGMTDate(Date date) {
        return new Date(date.getTime() + GMT_VIETNAM_TIME_OFFSET);
    }

    public static Date convertGMTDate(Date gmtDate, int hourOffset) {
        return new Date(gmtDate.getTime() + hourOffset * HOUR);
    }

    public static Timestamp convertGMTTimestamp(Timestamp gmtTimestamp,
                                                int hourOffset) {
        return new Timestamp(gmtTimestamp.getTime() + hourOffset * HOUR);
    }

    public static Timestamp getCurrentGMTTimestampExpiredYear(int offsetYear) {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.YEAR, offsetYear);
        return new Timestamp(now.getTime().getTime());
    }

    public static Timestamp getCurrentGMTTimestampExpiredMonth(int offsetMonth) {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.MONTH, offsetMonth);
        return new Timestamp(now.getTime().getTime());
    }

    public static Timestamp getCurrentGMTTimestampExpiredDay(int offsetDay) {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.DATE, offsetDay);
        return new Timestamp(now.getTime().getTime());
    }

    public static String format(Date date, String pattern) {
        DateFormat formatter = new SimpleDateFormat(pattern, Locale.US);
        return formatter.format(date);
    }

    public static String formatEast(Date date, String pattern) {
        DateFormat formatter = new SimpleDateFormat(pattern, Locale.CHINA);
        formatter.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        return formatter.format(date);
    }

    public static final String getDate(String pattern, Date date) {
        SimpleDateFormat df = null;
        String returnValue = "";

        if (date != null) {
            df = new SimpleDateFormat(pattern);
            returnValue = df.format(date);
        }

        return (returnValue);
    }

    /**
     * 获取时间的默认格式字符串：2008-12-01 21:01
     *
     * @param date
     * @return
     */
    public static String getDefaultDateString(Date date) {
        String str = "";

        str = format(date, DEFAULT_DATE_PATTERN);

        return str;
    }

    /**
     * 获当前时间的默认格式字符串，2008-12-10 21:10
     *
     * @return String
     */
    public static String getDefaultDateString() {
        return getDefaultDateString(new Date());
    }

    /**
     * 获取与当前时间距离n秒的日期
     *
     * @param date
     * @param seconds
     * @return
     */
    public static Date getDateWithSecondDistance(Date date, int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, seconds);

        date = calendar.getTime();
        return date;
    }

    /**
     * 获取与当前时间距离n分钟的日期
     *
     * @param date
     * @param minutes
     * @return
     */
    public static Date getDateWithMinuteDistance(Date date, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minutes);

        date = calendar.getTime();
        return date;
    }

    /**
     * 获取与当前时间距离n小时的日期
     *
     * @param date
     * @param hours
     * @return
     */
    public static Date getDateWithHourDistance(Date date, int hours) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR, hours);

        date = calendar.getTime();
        return date;
    }

    /**
     * 获取与当前时间距离n天的日期
     *
     * @param date
     * @param days
     * @return
     */
    public static Date getDateWithDayDistance(Date date, int days) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, days);

        date = calendar.getTime();
        return date;
    }

    /**
     * 获取与当前时间距离n个月的日期
     *
     * @param date
     * @param months
     * @return
     */
    public static Date getDateWithMonthDistance(Date date, int months) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, months);
        date = calendar.getTime();

        return date;
    }

    /**
     * 获取与当前时间距离n个月月末的日期
     *
     * @param date
     * @param months
     * @return
     */
    public static Date getMonthEndWithDistance(Date date, int months) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, months);
        calendar.set(Calendar.DATE, calendar.getMaximum(Calendar.DATE));

        return calendar.getTime();
    }

    /**
     * 获取与当前时间距离n年的日期
     *
     * @param date
     * @param years
     * @return
     */
    public static Date getDateWithYearDistance(Date date, int years) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, years);
        date = calendar.getTime();

        return date;
    }

    /**
     * 获取两个时间的毫秒数
     *
     * @param lastOccurredtime
     * @param datetime
     * @param pattern
     * @return
     */
    public static Long milliSecondsBetweenTwoTimes(String lastOccurredtime, String datetime, String pattern) {
        Long milliseconds = null;

        if (StrUtils.isNotBlank(lastOccurredtime) && StrUtils.isNotBlank(datetime)) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat(pattern);

                Calendar calLastOccurredTime = Calendar.getInstance();
                Date dtLastOccurredTime = sdf.parse(lastOccurredtime);
                calLastOccurredTime.setTime(dtLastOccurredTime);

                Date dtDatetime = sdf.parse(datetime);
                Calendar calDatetime = Calendar.getInstance();
                calDatetime.setTime(dtDatetime);

                milliseconds = (calDatetime.getTimeInMillis() - calLastOccurredTime.getTimeInMillis());

            } catch (ParseException e) {
                log.error(e.getMessage());
            }
        }

        return milliseconds;
    }

    /**
     * 将时间转化为时间戳：yyyyMMdHHmmss
     *
     * @return
     */
    public static String getTimeStamp(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_PATTERN3);
        return sdf.format(date);
    }

    /**
     * 将日期字符串转换为Date类型的日期
     *
     * @param date
     * @return
     */
    public static Date formatDate(String date) {
        if (!isTrue(date)) {
            throw new IllegalArgumentException("日期格式不正确");
        }

        Date currDT = new Date(System.currentTimeMillis());
        try {
            if (Pattern.matches(PATTERN_DATE, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_WITH_HM, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_WITH_HM).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_WITH_HMS, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_WITH_HMS).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_NOSEPARATOR).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR_WITH_HM, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_NOSEPARATOR_WITH_HM).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR_WITH_HMS, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_NOSEPARATOR_WITH_HMS).parse(date);
            } else {
                return currDT;
            }
        } catch (ParseException e) {
            return currDT;
        }
    }

    public static Date formatExcelDate(String date) {
        if (!isExcelTrue(date)) {
            throw new IllegalArgumentException("日期格式不正确");
        }

        Date currDT = new Date(System.currentTimeMillis());
        try {
            if (Pattern.matches(PATTERN_DATE, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_WITH_HM, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_WITH_HM).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_WITH_HMS, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_WITH_HMS).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_NOSEPARATOR).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR_WITH_HM, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_NOSEPARATOR_WITH_HM).parse(date);
            } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR_WITH_HMS, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA_NOSEPARATOR_WITH_HMS).parse(date);
            } else if (Pattern.matches(PATTERN_DATE1, date)) {
                return new SimpleDateFormat(SCHEMA_DATE_JAVA1).parse(date);
            } else {
                return currDT;
            }
        } catch (ParseException e) {
            return currDT;
        }
    }

    //~ Methods ================================================================

    /**
     * 判断日期字符是否符合指定格式
     *
     * @param date
     * @return
     */
    public static boolean isTrue(String date) {
        if (Pattern.matches(PATTERN_DATE, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE_WITH_HM, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE_WITH_HMS, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR_WITH_HM, date)) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isExcelTrue(String date) {
        if (Pattern.matches(PATTERN_DATE, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE_WITH_HM, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE_WITH_HMS, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE_NOSEPARATOR_WITH_HM, date)) {
            return true;
        } else if (Pattern.matches(PATTERN_DATE1, date)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 比较两个日期，如果date1比date2大则返回true，否则返回false
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean compareDate(String date1, String date2) {
        boolean isLarge = false;
        try {
            Date dt1 = null;
            Date dt2 = null;
            if (date1.trim().length() == 10) {
                dt1 = formatDate(date1, DEFAULT_DATE_ONLY_PATTERN);
                dt2 = formatDate(date2, DEFAULT_DATE_ONLY_PATTERN);
            } else {
                dt1 = formatDate(date1, DEFAULT_DATE_PATTERN2);
                dt2 = formatDate(date2, DEFAULT_DATE_PATTERN2);
            }

            if (dt1 != null && dt2 != null && dt1.getTime() > dt2.getTime()) {
                isLarge = true;
            } else {
                isLarge = false;
            }
        } catch (Exception e) {
            isLarge = false;
            log.error(e + "日期格式错误");
        }
        return isLarge;

    }

    /**
     * 比较两个日期(包含等于)，如果date1比date2大则返回true，否则返回false
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean compareDateTo(String date1, String date2) {
        boolean isLarge = false;
        try {
            Date dt1 = null;
            Date dt2 = null;
            if (date1.trim().length() == 10) {
                dt1 = formatDate(date1, DEFAULT_DATE_ONLY_PATTERN);
                dt2 = formatDate(date2, DEFAULT_DATE_ONLY_PATTERN);
            } else {
                dt1 = formatDate(date1, DEFAULT_DATE_PATTERN2);
                dt2 = formatDate(date2, DEFAULT_DATE_PATTERN2);
            }

            if (dt1 != null && dt2 != null && dt1.getTime() >= dt2.getTime()) {
                isLarge = true;
            } else {
                isLarge = false;
            }
        } catch (Exception e) {
            isLarge = false;
            log.error(e + "日期格式错误");
        }
        return isLarge;

    }

    /**
     * 将时间戳格式的字符串转换为日期对象
     *
     * @return
     */
    public static Date timeStamp2Date(String timeStamp) {
        try {
            long unixLong = Long.parseLong(timeStamp) * SECOND;// 时间戳是秒为单位
            return new Date(unixLong);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * 返回默认的日期格式 (yyyy-MM-dd)
     *
     * @return 默认日期格式(yyyy - MM - dd)
     */
    public static synchronized String getDatePattern() {
        return defaultDatePattern;
    }

    /**
     * 把日期按照指定格式转换为字符串
     *
     * @param date    输入的日期，如：2010-12-09 16:32:25
     * @param pattern 日期格式，如："yyyy-MM-dd"
     * @return 格式化的日期字符串，如：2010-12-09
     */
    public static final String getDateString(Date date, String pattern) {
        SimpleDateFormat df = null;
        String returnValue = "";
        if (pattern == null || "".equals(pattern)) {
            pattern = getDatePattern();
        }
        if (date != null) {
            df = new SimpleDateFormat(pattern);
            returnValue = df.format(date);
        }

        return (returnValue);
    }

    public static Date convertStringToDate(String strDate)
            throws ParseException {
        Date aDate = null;
        try {
            if (log.isDebugEnabled()) {
                log.debug("converting date with pattern: " + getDatePattern());
            }

            aDate = convertStringToDate(getDatePattern(), strDate);
        } catch (ParseException pe) {
            log.error("Could not convert '" + strDate + "' to a date, throwing exception");
            log.error(pe.getMessage());
            throw new ParseException(pe.getMessage(), pe.getErrorOffset());
        }

        return aDate;
    }

    /**
     * 把日期字符串转换为指定格式的日期
     *
     * @param pattern 日期格式
     * @param strDate 日期字符串
     * @return 转换得到的日期对象
     * @see SimpleDateFormat
     */
    public static final Date convertStringToDate(String pattern, String strDate)
            throws ParseException {
        SimpleDateFormat df = null;
        Date date = null;
        if (pattern == null || "".equals(pattern)) {
            pattern = getDatePattern();
        }
        df = new SimpleDateFormat(pattern);

        if (strDate != null && pattern != null && strDate.length() >= pattern.length()) {
            try {
                date = df.parse(strDate);
            } catch (ParseException pe) {
                log.error("ParseException: " + pe.getMessage());
                throw new ParseException(pe.getMessage(), pe.getErrorOffset());
            }
        }

        return (date);
    }

    public static String convertDateToString(String pattern, Date date) {
        if ((pattern == null) || (pattern.trim().length() == 0)) {
            return convertDateToString(date);
        }
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        if (date != null) {
            return format.format(date);
        }
        return "";
    }

    public static Date convertStringToDateTime(String strDate)
            throws ParseException {
        Date aDate = null;
        try {
            if (log.isDebugEnabled()) {
                log.debug("converting date with pattern: " + defaultDatePattern + " " + timePattern);
            }

            aDate = convertStringToDate(defaultDatePattern + " " + timePattern, strDate);
        } catch (ParseException pe) {
            log.error("Could not convert '" + strDate +
                    "' to a date, throwing exception");
            log.error(pe.getMessage());
            throw new ParseException(pe.getMessage(), pe.getErrorOffset());
        }

        return aDate;
    }

    /**
     * 取得当前日期(格式：yyyy-MM-dd)的日历对象
     *
     * @return 当前日期日历对象
     */
    public static Calendar getToday() {
        Date today = new Date();
        SimpleDateFormat df = new SimpleDateFormat(getDatePattern());

        // This seems like quite a hack (date -> string -> date),
        // but it works ;-)
        String todayAsString = df.format(today);
        Calendar cal = new GregorianCalendar();
        try {
            cal.setTime(convertStringToDate(null, todayAsString));
        } catch (ParseException e) {
            log.error(e.getMessage());
        }

        return cal;
    }

    public static Date getToday(int timezone) {
        return DateUtils.trunc(new Timestamp(System.currentTimeMillis() + timezone * HOUR));
    }

    public static Date getMonthFirstDay(Date date) {
        Date inDate = date;
        if (inDate == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_PATTERN12);
        String str = sdf.format(inDate) + "-01";
        sdf = new SimpleDateFormat(DEFAULT_DATE_ONLY_PATTERN);
        try {
            inDate = sdf.parse(str);
        } catch (ParseException e) {
            log.error(e.getMessage());
        }
        return inDate;
    }

    /**
     * 获取每月最后一天
     *
     * @param
     * @return
     */

    public String getMonthLastDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.roll(Calendar.DAY_OF_MONTH, -1);

        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_ONLY_PATTERN);
        String lastDayDate = sdf.format(cal.getTime()) + " 23:59:59";
        return lastDayDate;

    }

    public Date getMonthLastDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.roll(Calendar.DAY_OF_MONTH, -1);
        return cal.getTime();
    }

    public Date getMonthLastDateEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.roll(Calendar.DAY_OF_MONTH, -1);
        return getDateSecondEnd(cal.getTime());
    }

    public static Date getYearFirstDay(Date date) {
        Date inDate = date;
        if (inDate == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        String str = sdf.format(inDate) + "-01-01";
        sdf = new SimpleDateFormat(DEFAULT_DATE_ONLY_PATTERN);
        try {
            inDate = sdf.parse(str);
        } catch (ParseException e) {
            log.error(e.getMessage());
        }
        return inDate;
    }

    public static Date getYearLastDay(Date date) {
        Date inDate = date;
        if (inDate == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        String str = sdf.format(inDate) + "-12-31 23:59:59";
        sdf = new SimpleDateFormat(DEFAULT_DATE_PATTERN2);
        try {
            inDate = sdf.parse(str);
        } catch (ParseException e) {
            log.error(e.getMessage());
        }
        return inDate;
    }

    /**
     * 得到指定日期的指定部分增加一个数值之后的日期，闰年由Calendar自己判断，<br>
     *
     * @param dateString 日期字符串
     * @param pattern    日期格式
     * @param addType    增加的部分，"yyyy"或"yy"或"y"为年份，"MM"或"M"为月份,"dd"或"d"为日
     * @param addValue   增加的数值，正数表示增加，负数表示减少
     * @return 返回日期值的字符串，格式：yyyy-MM-dd hh:mm:ss
     */
    public static String dateAdd(String dateString, String pattern, String addType, int addValue) {
        String ret = "";
        SimpleDateFormat df = new SimpleDateFormat(pattern);
        Date date = null;
        try {
            date = df.parse(dateString);
            ret = dateAdd(date, addType, addValue);
        } catch (ParseException e) {
            log.error(e.getMessage());
        }

        return ret;
    }

    /**
     * 得到指定日期的指定部分增加一个数值之后的日期，闰年由Calendar自己判断，<br>
     *
     * @param date     传入的日期
     * @param addType  增加的部分，"yyyy"或"yy"或"y"为年份，"MM"或"M"为月份,"dd"或"d"为日
     * @param addValue 增加的数值，正数表示增加，负数表示减少
     * @return 返回日期值的字符串，格式：yyyy-MM-dd hh:mm:ss
     */
    public static String dateAdd(Date date, String addType, int addValue) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int addPart = 1;
        if ("yyyy".equals(addType.toLowerCase().trim()) || "yy".equals(addType.toLowerCase().trim()) || "y".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.YEAR;
        }
        if ("mm".equals(addType.toLowerCase().trim()) || "m".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.MONTH;
        }
        if ("ww".equals(addType.toLowerCase().trim()) || "w".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.DAY_OF_WEEK;
        }
        if ("dd".equals(addType.toLowerCase().trim()) || "d".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.DATE;
        }
        cal.add(addPart, addValue);
        return DateUtils.format(cal.getTime(), DEFAULT_DATE_PATTERN2);
    }

    /**
     * 得到指定日期的指定部分增加一个数值之后的日期，闰年由Calendar自己判断，<br>
     *
     * @param date     传入的日期
     * @param addType  增加的部分，"yyyy"或"yy"或"y"为年份，"MM"或"M"为月份,"dd"或"d"为日
     * @param addValue 增加的数值，正数表示增加，负数表示减少
     * @return 返回日期值的字符串，格式：yyyy-MM-dd hh:mm:ss
     */
    public static String dateAddDays(Date date, String addType, int addValue) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int addPart = 1;
        if ("yyyy".equals(addType.toLowerCase().trim()) || "yy".equals(addType.toLowerCase().trim()) || "y".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.YEAR;
        }
        if ("mm".equals(addType.toLowerCase().trim()) || "m".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.MONTH;
        }
        if ("ww".equals(addType.toLowerCase().trim()) || "w".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.DAY_OF_WEEK;
        }
        if ("dd".equals(addType.toLowerCase().trim()) || "d".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.DATE;
        }
        cal.add(addPart, addValue);
        return DateUtils.format(cal.getTime(), DEFAULT_DATE_PATTERN2);
    }

    public static String getTimeDiff(long tStart, long tEnd) {
        long sec = 1000;
        long min = sec * 60;
        long hour = min * 60;
        long day = hour * 24;
        long month = day * 30;
        long year = 365 * day;

        // UTC is temporary realized to hold the time in miliss passed from ..
        // 1970
        long diffInMills = tEnd - tStart;
        if (diffInMills < min) {
            return diffInMills / sec + " [s]";
        } else if (diffInMills < hour) {
            long m = diffInMills / min;
            long s = (diffInMills - m * min) / sec;
            return m + MIN_STR + s + " [s]";
        } else if (diffInMills < day) {
            long h = diffInMills / hour;
            long m = (diffInMills - h * hour) / min;
            long s = (diffInMills - h * hour - m * min) / sec;
            return h + H_STR + m + MIN_STR + s + " [s]";
        } else if (diffInMills < month) {
            long d = diffInMills / day;
            long h = (diffInMills - d * day) / hour;
            long m = (diffInMills - d * day - h * hour) / min;
            long s = (diffInMills - d * day - h * hour - m * min) / sec;
            return d + D_STR + h + H_STR + m + MIN_STR + s + " [s]";
        } else if (diffInMills < year) {
            long mn = diffInMills / month;
            long d = (diffInMills - mn * month) / day;
            long h = (diffInMills - mn * month - d * day) / hour;
            long m = (diffInMills - mn * month - d * day - h * hour) / min;
            long s = (diffInMills - mn * month - d * day - h * hour - m * min) / sec;
            return mn + " [m] " + d + D_STR + h + H_STR + m + MIN_STR + s + " [s]";
        } else { /** if (diffInMills>=year) **/
            long y = diffInMills / year;
            long mn = (diffInMills - y * year) / month;
            long d = (diffInMills - y * year - mn * month) / day;
            long h = (diffInMills - y * year - mn * month - d * day) / hour;
            long m = (diffInMills - y * year - mn * month - d * day - h * hour) / min;
            long s = (diffInMills - y * year - mn * month - d * day - h * hour - m * min) / sec;
            return y + " [y] " + mn + " [m] " + d + D_STR + h + H_STR + m + MIN_STR + s + " [s]";
        }
    }

    public static final String getDate(Date aDate) {
        SimpleDateFormat df = null;
        String returnValue = "";

        if (aDate != null) {
            df = new SimpleDateFormat(getDatePattern());
            returnValue = df.format(aDate);
        }

        return returnValue;
    }

    public static final String convertDateToString(Date aDate) {
        return getDateTime(getDatePattern(), aDate);
    }

    public static final String getDateTime(Date aDate) {
        SimpleDateFormat df = null;
        String returnValue = "";

        if (aDate != null) {
            df = new SimpleDateFormat(defaultDatePattern + " " + timePattern);
            returnValue = df.format(aDate);
        }

        return returnValue;
    }

    public static final String getDateTime(String aMask, Date aDate) {
        SimpleDateFormat df = null;
        String returnValue = "";

        if (aDate == null) {
            log.info("aDate is null!");
        } else {
            df = new SimpleDateFormat(aMask);
            returnValue = df.format(aDate);
        }

        return returnValue;
    }


    /**
     * 给日期字符串添时分秒（yyyy/MM/dd或者yyyy-MM-dd） b=true时，添加"00:00:00", b=false时,添加"23:59:59"
     *
     * @param dateStr
     * @param b
     * @return
     */
    public static final String appendHMS(String dateStr, boolean b) {
        if (dateStr.length() > 10) {
            return dateStr;
        }
        if (b) {
            return new StringBuffer(dateStr).append(" 00:00:00").toString();
        } else {
            return new StringBuffer(dateStr).append(" 23:59:59").toString();
        }
    }

    public static Date addSecond(Date date, int amount) {
        return add(date, Calendar.SECOND, amount);
    }

    public static Date addMinutes(Date date, int amount) {
        return add(date, 12, amount);
    }

    public static Date addHour(Date date, int amount) {
        return add(date, 10, amount);
    }

    public static Date addDays(Date date, int amount) {
        return add(date, 5, amount);
    }

    public static Date addMonths(Date date, int amount) {
        return add(date, 2, amount);
    }

    public static Date addYears(Date date, int amount) {
        return add(date, 1, amount);
    }

    private static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("日期对象不允许为null!");
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    public static Date getCurrentDateStart() {
        Calendar calendar = Calendar.getInstance();
        // 将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        // 将秒至0
        calendar.set(Calendar.SECOND, 0);
        // 将毫秒至0
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getCurrentDateEnd() {
        Calendar calendar = Calendar.getInstance();
        // 将当前月加1；
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        // 将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        // 将秒至0
        calendar.set(Calendar.SECOND, 0);
        // 基础上减去1毫秒
        calendar.set(Calendar.MILLISECOND, -1);
        return calendar.getTime();
    }

    public static Date getDateStart(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        // 将秒至0
        calendar.set(Calendar.SECOND, 0);
        // 将毫秒至0
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getDateEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        ///将当前月加1；
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        // 将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        // 将秒至0
        calendar.set(Calendar.SECOND, 0);
        // 基础上减去1毫秒
        calendar.set(Calendar.MILLISECOND, -1);
        return calendar.getTime();
    }

    public static Date getDateSecondEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 将当前月加1；
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        // 将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        // 将秒减1
        calendar.set(Calendar.SECOND, -1);
        // 将毫秒至0
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }


    public static Timestamp convertStringToTimestamp(String time, String format) {
        DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.DEFAULT);
        if (null == time || "".equals(time)) {
            return null;
        }
        if (null != format && !"".equals(format)) {
            dateFormat = new SimpleDateFormat(format);
        }
        Timestamp timestamp = null;
        try {
            timestamp = new Timestamp(dateFormat.parse(time).getTime());
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return timestamp;
    }

    public static Date getCurrentDate() {
        return DateUtils.getCurrentGMTTimestamp();
    }

    public static Date getCurrentSysDate() {
        return DateUtils.getCurrentGMTTimestamp();
    }

    public static BigDecimal getDateReduce(Date reduceDate, Date minuendDate) {
        long reduceDateLong = reduceDate.getTime();
        long minuendDateLong = minuendDate.getTime();
        // 结束时间-开始时间 = 天数
        BigDecimal day = BigDecimal.valueOf((reduceDateLong - minuendDateLong) / (24 * 60 * 60 * 1000));
        return day;
    }

    /**
     * 月份相减
     *
     * @param start
     * @param end
     * @return
     */
    public static int getMonthNum(Date start, Date end) {
        Calendar birthday = Calendar.getInstance();
        birthday.setTime(start);
        Calendar now = Calendar.getInstance();
        now.setTime(end);
        int day = now.get(Calendar.DAY_OF_MONTH) - birthday.get(Calendar.DAY_OF_MONTH);
        int month = now.get(Calendar.MONTH) - birthday.get(Calendar.MONTH);
        int year = now.get(Calendar.YEAR) - birthday.get(Calendar.YEAR);
// 按照减法原理，先day相减，不够向month借；然后month相减，不够向year借；最后year相减。
        if (day < 0) {
            month -= 1;
            now.add(Calendar.MONTH, -1);// 得到上一个月，用来得到上个月的天数。
            // day +=  now.getActualMaximum(Calendar.DAY_OF_MONTH);
        }
        if (month < 0) {
            month = (month + 12) % 12;
            year--;
        }
        if (year > 0) {
            month = year * 12 + month;
        }
        return month;
    }

    /**
     * 获取月份第一天
     *
     * @param date
     * @return
     */
    public static String getFirstDay(Date date) {
        if (date == null) {
            return null;
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);
        return new SimpleDateFormat(DateUtils.DEFAULT_DATE_ONLY_PATTERN).format(c.getTime());
    }

    /**
     * 获取月份最后一天
     *
     * @param date
     * @return
     */
    public static String getLastDay(Date date) {
        if (date == null) {
            return null;
        }
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        return new SimpleDateFormat(DateUtils.DEFAULT_DATE_ONLY_PATTERN).format(ca.getTime());
    }

    public static String[] dateToStr(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_PATTERN12);
        SimpleDateFormat sdf1 = new SimpleDateFormat("dd");
        // 年月
        String str = sdf.format(date);
        // 日
        String str1 = sdf1.format(date);
        String[] dateStr = new String[2];
        dateStr[0] = str;
        dateStr[1] = str1;
        return dateStr;
    }

    public static Date transPeriodDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_PATTERN12);
        SimpleDateFormat sdf2 = new SimpleDateFormat(DEFAULT_DATE_ONLY_PATTERN);
        String str = sdf.format(date);
        Date transDate = null;
        try {
            transDate = sdf2.parse(str + "-01");
        } catch (ParseException e) {
            log.info(e.getMessage());
        }
        return transDate;
    }

    public static Date max(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return null;
        } else {
            return date1.after(date2) ? date1 : date2;
        }
    }

    /**
     * add by jianl
     *
     * @param date1
     * @param date2
     * @return
     */
    public static Date max2(Date date1, Date date2) {
        if (date1 == null) {
            return date2;
        } else if (date2 == null) {
            return date1;
        } else {
            return date1.after(date2) ? date1 : date2;
        }
    }

    public static Date min(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return null;
        } else {
            return date1.before(date2) ? date1 : date2;
        }
    }

    public static Date min2(Date date1, Date date2) {
        if (date1 == null) {
            return date2;
        } else if (date2 == null) {
            return date1;
        } else {
            return date1.before(date2) ? date1 : date2;
        }
    }

    public static Date trunc(Date date) {
        String datestr = new SimpleDateFormat(DateUtils.DEFAULT_DATE_ONLY_PATTERN).format(date);
        return formatDate(datestr, DateUtils.DEFAULT_DATE_ONLY_PATTERN);
    }

    public static Date[] getWeekDay(Date day, int weekOfDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(day);
        while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
            calendar.add(Calendar.DAY_OF_WEEK, -1);
        }
        Date[] dates = new Date[weekOfDay];
        for (int i = 0; i < weekOfDay; i++) {
            dates[i] = calendar.getTime();
            calendar.add(Calendar.DATE, 1);
        }
        return dates;
    }

    public static Date convertToDate(XMLGregorianCalendar cal) {
        GregorianCalendar ca = null;
        if (cal != null && cal.toGregorianCalendar() != null) {
            ca = cal.toGregorianCalendar();
            return ca.getTime();
        }
        return null;
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param timeStart
     * @param timeEnd
     * @return
     */
    public static List<String> collectLocalDates(Date timeStart, Date timeEnd) {
        return collectLocalDates(LocalDate.parse(DateUtils.format(timeStart, DateUtils.DEFAULT_DATE_ONLY_PATTERN)), LocalDate.parse(DateUtils.format(timeEnd, DateUtils.DEFAULT_DATE_ONLY_PATTERN)));
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param timeStart
     * @param timeEnd
     * @param descList
     * @return
     */
    public static List<String> collectLocalDates(Date timeStart, Date timeEnd, List<String> descList) {
        return collectLocalDates(LocalDate.parse(DateUtils.format(timeStart, DateUtils.DEFAULT_DATE_ONLY_PATTERN)), LocalDate.parse(DateUtils.format(timeEnd, DateUtils.DEFAULT_DATE_ONLY_PATTERN)), descList);
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param timeStart
     * @param timeEnd
     * @return
     */
    public static List<String> collectLocalDates(String timeStart, String timeEnd) {
        return collectLocalDates(LocalDate.parse(timeStart), LocalDate.parse(timeEnd));
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param start
     * @param end
     * @return
     */
    public static List<String> collectLocalDates(LocalDate start, LocalDate end) {
        // 用起始时间作为流的源头，按照每次加一天的方式创建一个无限流
        return Stream.iterate(start, localDate -> localDate.plusDays(1))
                // 截断无限流，长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                // 由于最后要的是字符串，所以map转换一下
                .map(LocalDate::toString)
                // 把流收集为List
                .collect(Collectors.toList());
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param start
     * @param end
     * @param descList
     * @return
     */
    public static List<String> collectLocalDates(LocalDate start, LocalDate end, List<String> descList) {
        List<String> list = Lists.newArrayList();
        // 用起始时间作为流的源头，按照每次加一天的方式创建一个无限流
        Stream.iterate(start, localDate -> localDate.plusDays(1))
                // 截断无限流，长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                .forEach(localDate -> {
                    descList.forEach(desc -> {
                        list.add(String.format("%s%s(%s)", localDate.toString(),
                                desc, DateUtils.getWeek(localDate)));
                    });
                });
        return list;
    }

    /**
     * @Description: 比对两个日期相差多少天、小时、 分、秒
     * @Author: EX_LIUGD
     * @date: 2020/5/27
     */
    public static long differentDaysByDate(Date date3, Date date4, String unit) {
        Date date2 = DateUtils.max(date3, date4);
        Date date1 = DateUtils.min(date3, date4);
        if (date1 == null || date2 == null) {
            return -1L;
        }
        switch (unit) {
            case "d":
                return ((date2.getTime() - date1.getTime()) / DateUtils.DAY);
            case "h":
                return ((date2.getTime() - date1.getTime()) / DateUtils.HOUR);
            case "m":
                return ((date2.getTime() - date1.getTime()) / DateUtils.MINUTE);
            default:
                return ((date2.getTime() - date1.getTime()) / DateUtils.SECOND);
        }
    }

    public static BigDecimal dateDiff(Date date3, Date date4, String unit) {
        Date date2 = DateUtils.max(date3, date4);
        Date date1 = DateUtils.min(date3, date4);
        if (date1 == null || date2 == null) {
            return null;
        }
        switch (unit) {
            case "d":
                return BigDecimal.valueOf(date2.getTime())
                        .subtract(BigDecimal.valueOf(date1.getTime()))
                        .divide(BigDecimal.valueOf(DateUtils.DAY), 4, RoundingMode.HALF_UP);
            case "h":
                return BigDecimal.valueOf(date2.getTime())
                        .subtract(BigDecimal.valueOf(date1.getTime()))
                        .divide(BigDecimal.valueOf(DateUtils.HOUR), 4, RoundingMode.HALF_UP);
            case "m":
                return BigDecimal.valueOf(date2.getTime())
                        .subtract(BigDecimal.valueOf(date1.getTime()))
                        .divide(BigDecimal.valueOf(DateUtils.MINUTE), 4, RoundingMode.HALF_UP);
            default:
                return BigDecimal.valueOf(date2.getTime())
                        .subtract(BigDecimal.valueOf(date1.getTime()))
                        .divide(BigDecimal.valueOf(DateUtils.SECOND), 4, RoundingMode.HALF_UP);
        }
    }

    /**
     * @Description: 比对两个日期相差多少天、小时、 分、秒
     * @Author: EX_LIUGD
     * @date: 2020/5/27
     */
    public static long differentDaysByDate(String date3, String date4, String unit) {
        Date date1 = DateUtils.formatDate(date3);
        Date date2 = DateUtils.formatDate(date4);
        return DateUtils.differentDaysByDate(date1, date2, unit);
    }



    /**
     * @Description: 更改日期到当天 时分秒不变
     * @Author: ex_liangxn1
     * @create: 2020/10/6
     */


    /**
     * @Description: 获取当前东8区时间
     * @Author: ex_liangxn1
     * @create: 2020/10/19
     */
    public static Date getCurrentEast8Date() {
        Calendar now = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
        return now.getTime();
    }

    /**
     * @Description: 获取当前东8区年
     * @Author: ex_liangxn1
     * @create: 2020/10/19
     */
    public static String getCurrentEast8Year() {
        Calendar now = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
        return now.get(Calendar.YEAR) + "";
    }

    /**
     * @Description: 获取当前东8区月
     * @Author: ex_liangxn1
     * @create: 2020/10/19
     */
    public static int getCurrentEast8Month() {
        Calendar now = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
        return now.get(Calendar.MONTH) + 1;
    }

    /**
     * 得到指定日期的指定部分增加一个数值之后的日期，闰年由Calendar自己判断，<br>
     *
     * @param date     传入的日期
     * @param addType  增加的部分，"yyyy"或"yy"或"y"为年份，"MM"或"M"为月份,"dd"或"d"为日
     * @param addValue 增加的数值，正数表示增加，负数表示减少
     * @return 返回日期值的字符串，格式：yyyy-MM-dd hh:mm:ss
     */
    public static Date dateAddReturnDate(Date date, String addType, int addValue) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int addPart = 1;
        if ("yyyy".equals(addType.toLowerCase().trim()) || "yy".equals(addType.toLowerCase().trim()) || "y".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.YEAR;
        }
        if ("mm".equals(addType.toLowerCase().trim()) || "m".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.MONTH;
        }
        if ("ww".equals(addType.toLowerCase().trim()) || "w".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.DAY_OF_WEEK;
        }
        if ("dd".equals(addType.toLowerCase().trim()) || "d".equals(addType.toLowerCase().trim())) {
            addPart = Calendar.DATE;
        }
        cal.add(addPart, addValue);
        return cal.getTime();
    }

    public static String getWeek(Date date) {
        String[] weeks = {"日", "一", "二", "三", "四", "五", "六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (week_index < 0) {
            week_index = 0;
        }
        return weeks[week_index];
    }

    public static String getWeek(LocalDate date) {
        String[] weeks = {"一", "二", "三", "四", "五", "六", "日"};
        int week_index = date.getDayOfWeek().getValue() - 1;
        if (week_index < 0) {
            week_index = 0;
        }
        return weeks[week_index];
    }

    public static String getWeekEnglish(Date date) {
        String[] weeks = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (week_index < 0) {
            week_index = 0;
        }
        return weeks[week_index];
    }

    /**
     * <p>比较两个日期区间是否存在交集
     *
     * @param startDate1
     * @param endDate1
     * @param startDate2
     * @param endDate2
     * @return true：交叉 /false:不交叉
     */
    public static boolean overlap(Date startDate1, Date endDate1, Date startDate2, Date endDate2) {
        // return startDate2< endDate1 && endDate2 > startDate1;
        return startDate2.before(endDate1) && startDate1.before(endDate2);
    }

    // 获取当前旬的最后一天
    public static Date getLastDayOfTenDays(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int lastDayOfTenDays = 0;
        if (dayOfMonth <= 10) {
            lastDayOfTenDays = 10;
        } else if (dayOfMonth <= 20) {
            lastDayOfTenDays = 20;
        } else {
            lastDayOfTenDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        }
        calendar.set(Calendar.DAY_OF_MONTH, lastDayOfTenDays);
        return calendar.getTime();
    }

    /**
     * @param date1 日期1
     * @param date2 日期2
     * @return
     * @title: dateCompareYYMMDD
     * @description: 比较日期年月日
     */
    public static int dateCompareYYMMDD(Date date1, Date date2) {
        if (Objects.isNull(date1) || Objects.isNull(date2)) {
            return 0;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String dateFirst = dateFormat.format(date1);
        String dateLast = dateFormat.format(date2);
        int dateFirstIntVal = Integer.parseInt(dateFirst);
        int dateLastIntVal = Integer.parseInt(dateLast);
        if (dateFirstIntVal > dateLastIntVal) {
            return 1;
        } else if (dateFirstIntVal < dateLastIntVal) {
            return -1;
        }
        return 0;
    }

    /**
     * @param date1 日期1
     * @param date2 日期2
     * @return
     * @title: dateCompare_yyyyMMddhhmmss
     * @description: 比较日期年月日时分秒
     */
    @SneakyThrows
    public static int dateCompare_yyyyMMddhhmmss(Date date1, Date date2) {
        if (Objects.isNull(date1) || Objects.isNull(date2)) {
            return 0;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date dateFirst = dateFormat.parse(dateFormat.format(date1));
        Date dateLast = dateFormat.parse(dateFormat.format(date2));
        return dateFirst.compareTo(dateLast);
    }

    /**
     * 获取当前日期的对应的星期一
     * 星期一为第一天
     *
     * @param date
     * @return
     */
    public static Date getWeekMonday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 星期一为第一天
        int weekIndex = cal.get(Calendar.DAY_OF_WEEK) - 1;

        // 因为是以星期一为第一天，所以要判断weekIndex等于0时，要向前推6天。
        weekIndex = (weekIndex == 0 ? (7 - 1) : (weekIndex - 1));

        // 本周第一天
        return formatDate(format(DateUtil.offsetDay(date, -weekIndex), DEFAULT_DATE_ONLY_PATTERN), DEFAULT_DATE_ONLY_PATTERN);
    }

    /**
     * 获取当前日期的对应的星期日
     * 星期一为第一天
     *
     * @param date
     * @return
     */
    public static Date getWeekSunday(Date date) {
        return DateUtil.offsetDay(date, 6);
    }

    /**
     * 获取指定日期所在周的周日
     *
     * @param date 日期
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        // 如果是周日直接返回
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            return c.getTime();
        }
        c.add(Calendar.DATE, 7 - c.get(Calendar.DAY_OF_WEEK) + 1);
        return c.getTime();
    }

    /**
     * 获取月份天数
     *
     * @param date
     * @return
     */
    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取两个日期之间的所有月份 (年月)
     *
     * @param startTime
     * @param endTime
     * @return：YYYY-MM
     */
    public static List<Date> getMonthBetweenDate(String startTime, String endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_PATTERN12);
        // 声明保存日期集合
        List<Date> list = new ArrayList<>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            // 用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {
                // 把日期添加到集合
                list.add(startDate);
                // 设置日期
                calendar.setTime(startDate);
                // 把日期增加一天
                calendar.add(Calendar.MONTH, 1);
                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        } catch (ParseException e) {
            log.error(e.getMessage());
        }
        return list;
    }

    public static List<Range> splitToWeeks(Date start, Date end) {
        List<Range> rangeList = new ArrayList<>();
        Date weekEnd = DateUtils.getLastDayOfWeek(start);
        while (weekEnd.compareTo(end) < 0) {
            Range range = new Range(start, weekEnd);
            rangeList.add(range);
            start = DateUtils.getDateStart(DateUtils.getDateWithDayDistance(weekEnd, 1));
            weekEnd = DateUtils.getLastDayOfWeek(start);
        }
        Range range = new Range(start, end);
        rangeList.add(range);
        return rangeList;
    }

    public static List<Range> splitToMonth(Date start, Date end) {
        List<Range> rangeList = new ArrayList<>();
        Date monthEnd = DateUtils.formatDate(DateUtils.getMonthLastDay(start));
        while (monthEnd.compareTo(end) < 0) {
            Range range = new Range(start, monthEnd);
            rangeList.add(range);
            start = DateUtils.getDateStart(DateUtils.getDateWithDayDistance(monthEnd, 1));
            monthEnd = DateUtils.formatDate(DateUtils.getMonthLastDay(start));
        }
        Range range = new Range(start, end);
        rangeList.add(range);
        return rangeList;
    }

    public static List<String> getDatesBetween(Date beginDate, Date endDate) {
        SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd");
        String beginDateString = formatter1.format(beginDate);
        String endDateString = formatter1.format(endDate);

        List<String> dates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate start = LocalDate.parse(beginDateString, formatter);
        LocalDate end = LocalDate.parse(endDateString, formatter);
        while (!start.isAfter(end)) {
            dates.add(start.format(formatter));
            start = start.plusDays(1);
        }
        return dates;
    }

    @Data
    @AllArgsConstructor
    public static class Range {
        Date start;
        Date end;
    }

    /**
     * displayMonth 日期格式是  yyyy-MM
     *
     * @param displayMonth
     * @return
     */
    public static List<Date> getMonthRange(String displayMonth) {
        if (StrUtils.isBlank(displayMonth)) {
            return Lists.newArrayList();
        }
        List<Date> dateList = Lists.newArrayList();
        DateTime dateTime = null;
        if (displayMonth.length() == 7) {
            dateTime = DateUtil.parse(displayMonth, "yyyy-MM");
        } else {
            dateTime = DateUtils.parse(displayMonth);
        }
        dateList.add(DateUtil.beginOfMonth(dateTime));
        dateList.add(DateUtil.endOfMonth(dateTime));

        return dateList.stream().sorted().distinct().collect(Collectors.toList());
    }

    /**
     * 当前日期是否在日期指定范围内<br>
     * 起始日期和结束日期可以互换
     *
     * @param date      被检查的日期
     * @param beginDate 起始日期（包含）
     * @param endDate   结束日期（不包含）
     */
    public static boolean isTimeRange(Date date, Date beginDate, Date endDate) {
        long beginMills = beginDate.getTime();
        long endMills = endDate.getTime();
        long thisMills = date.getTime();
        return thisMills >= Math.min(beginMills, endMills) && thisMills < Math.max(beginMills, endMills);
    }

    /**
     * 叠加时段是否覆盖了整整一天
     *
     * @param intervalList
     * @return
     */
    public static boolean isFullDayCovered(List<String> intervalList) {

        boolean[] coverage = new boolean[INTERVALS_PER_DAY];

        for (String interval : intervalList) {
            String[] parts = interval.split("-");
            String[] startParts = parts[0].split(":");
            String[] endParts = parts[1].split(":");

            int startHour = Integer.parseInt(startParts[0]);
            int startMinute = Integer.parseInt(startParts[1]);
            int endHour = Integer.parseInt(endParts[0]);
            int endMinute = Integer.parseInt(endParts[1]);

            // Calculate start and end index in minute intervals
            int startIndex = startHour * 60 + startMinute;
            int endIndex = endHour * 60 + endMinute;

            // Handle cross-day intervals
            if (startIndex >= endIndex) {
                // The end time is on the next day, so we need to cover the rest of this day and the beginning of the next day
                for (int i = startIndex; i < INTERVALS_PER_DAY; i++) {
                    coverage[i] = true;
                }
                for (int i = 0; i < endIndex; i++) {
                    coverage[i] = true;
                }
            } else {
                // Normal case where the interval does not cross midnight
                for (int i = startIndex; i < endIndex; i++) {
                    if (i >= 0 && i < INTERVALS_PER_DAY) {
                        coverage[i] = true;
                    }
                }
            }
        }
        for (boolean b : coverage) {
            if (!b) {
                return false;
            }
        }
        return true;
    }

    public static Duration calculateDuration(Date startDate, Date endDate) {
        // 将 Date 转换为 Instant
        Instant startInstant = startDate.toInstant();
        Instant endInstant = endDate.toInstant();
        // 使用 Duration.between() 方法计算时间间隔
        return Duration.between(startInstant, endInstant);
    }

    public static void main(String[] args) throws ParseException {
//        List<String> timeSlots = new ArrayList<>();
//        timeSlots.add("10:00:00-12:00:00");
//        timeSlots.add("14:00:00-16:00:00");
//        timeSlots.add("18:00:00-20:00:00");
//        Date now = new Date();
//        String closestSlot = findClosestTimeSlot(now, timeSlots);
//        System.out.println(closestSlot);
    }
}
